﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;

namespace zy_simu.Data
{
    public static class KgConsoleManager
    {
        [DllImport("kernel32.dll")]
        private static extern bool AllocConsole();
        [DllImport("kernel32.dll")]
        private static extern bool FreeConsole();
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetConsoleWindow();
        [DllImport("kernel32.dll")]
        private static extern int GetConsoleOutputCP();
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        private static extern bool PostMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr GetStdHandle(int nStdHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);

        public const int STD_OUTPUT_HANDLE = -11;
        public const int STD_INPUT_HANDLE = -10;
        public const int STD_ERROR_HANDLE = -12;
        public const uint GENERIC_WRITE = 0x40000000;
        public const uint GENERIC_READ = 0x80000000;

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPTStr)] string filename,
                                               [MarshalAs(UnmanagedType.U4)] uint access,
                                               [MarshalAs(UnmanagedType.U4)] FileShare share,
                                                                                 IntPtr securityAttributes,
                                               [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
                                               [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
                                                                                 IntPtr templateFile);


        private static void OverrideRedirection()
        {
            var hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            var hRealOut = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FileShare.Write, IntPtr.Zero, FileMode.OpenOrCreate, 0, IntPtr.Zero);
            if (hRealOut != hOut)
            {
                SetStdHandle(STD_OUTPUT_HANDLE, hRealOut);
                Console.SetOut(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true });
            }
        }

        public static bool HasConsole
        {
            get { return GetConsoleWindow() != IntPtr.Zero; }
        }
        /// Creates a new console instance if the process is not attached to a console already.  
        public static void Show()
        {
            if (GetConsoleWindow() == IntPtr.Zero)
            {
                AllocConsole();
                OverrideRedirection();
            }
        }
        /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.   
        public static void Hide()
        {
            IntPtr hConsole = GetConsoleWindow();
            if (hConsole != IntPtr.Zero)
            {
                PostMessageW(hConsole, 0x0010, IntPtr.Zero, IntPtr.Zero);
                FreeConsole();
            }
        }



        // 创建log输出子窗口 ==================================================================================================
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
        // 等待窗口创建并获取句柄
        static IntPtr WaitForWindowHandle(string title, int maxRetry = 10, int delay = 500)
        {
            IntPtr hWnd = IntPtr.Zero;
            for (int i = 0; i < maxRetry; i++)
            {
                hWnd = FindWindow(null, title);
                if (hWnd != IntPtr.Zero) break;
                Thread.Sleep(delay);
            }
            return hWnd;
        }
        // 计算并设置窗口位置
        static void ArrangeWindows(IntPtr hWnd, int pos)
        {

            // 获取主屏幕工作区（排除任务栏）右侧半屏尺寸
            int rightWidth = (int)(SystemParameters.WorkArea.Width / 2);
            int halfHeight = (int)(SystemParameters.WorkArea.Height / 2);

            // 调整第一个窗口（上半部分）
            MoveWindow(hWnd, rightWidth, pos* halfHeight, rightWidth, halfHeight, true);
        }
        public static Process StartChildConsole(string title)
        {
            var p = new Process();
            p.StartInfo.FileName = "LogConsole.exe";
            p.StartInfo.Arguments = title;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardError = true;
            //p.StartInfo.CreateNoWindow = true;
            //p.StartInfo.StandardInputEncoding = Encoding.UTF8; // 设置编码
            p.Start();

            IntPtr hWnd1 = WaitForWindowHandle(title);
            if(title == "M0")
                ArrangeWindows(hWnd1, 0);
            else if(title == "Cat1")
                ArrangeWindows(hWnd1, 1);
            return p;
        }
    }
}
